home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / TCPCMD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-06  |  27.1 KB  |  1,158 lines

  1. /* TCP control and status routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by G1EMM
  5.  * Mods by WG7J
  6.  * Mods by WA3DSP
  7.  * Mods by PA0GRI
  8.  * Copyright 1992 Gerard J van der Grinten, PA0GRI
  9.  */
  10. #include "global.h"
  11. #include "ctype.h"
  12. #include "commands.h"
  13. #ifdef MSDOS
  14. #include "socket.h"
  15. #else
  16. #include "timer.h"
  17. #include "mbuf.h"
  18. #endif
  19. #include "netuser.h"
  20. #include "internet.h"
  21. #include "iface.h"
  22.  
  23. #if !defined(_lint)
  24. static char rcsid[] OPTIONAL = "$Id: tcpcmd.c,v 1.21 1997/09/07 00:31:16 root Exp root $";
  25. #endif
  26.  
  27. #ifdef  TCPACCESS
  28. static int doaccess (int argc, char *argv[], void *p);
  29. #endif
  30.  
  31. #if defined(TCPACCESS) || defined(UDPACCESS)
  32. int do_tcpudp_access (int argc, char *argv[], void *p);
  33. static void addtaccess (struct rtaccess **tpacc, uint32 target, unsigned int bits, int16 low, int16 high, int16 permit);
  34. #endif
  35.  
  36. static int tcpirtt (int argc, char *argv[], void *p);
  37. static int dotcpirtt (int argc, char *argv[], void *p);
  38. static int tcpmss (int argc, char *argv[], void *p);
  39. static int dotcpmss (int argc, char *argv[], void *p);
  40. static int dortt (int argc, char *argv[], void *p);
  41. static int dotcpclean (int argc, char *argv[], void *p);
  42. static int dotcpkick (int argc, char *argv[], void *p);
  43. static int dotcpreset (int argc, char *argv[], void *p);
  44. static int dotcpretries (int argc, char *argv[], void *p);
  45. static int tcpretries (int argc, char *argv[], void *p);
  46. static int dotcpstat (int argc, char *argv[], void *p);
  47. static int dotcpconnect (int argc, char *argv[], void *p);
  48. static int dotcptimer (int argc, char *argv[], void *p);
  49. static int tcptimer (int argc, char *argv[], void *p);
  50. static int dotcptr (int argc, char *argv[], void *p);
  51. static int dotcpwindow (int argc, char *argv[], void *p);
  52. static int tcpwindow (int argc, char *argv[], void *p);
  53. static int dotcpmaxwait (int argc, char *argv[], void *p);
  54. static int tcpmaxwait (int argc, char *argv[], void *p);
  55. static int dotcpsyndata (int argc, char *argv[], void *p);
  56. static int tcpsyndata (int argc, char *argv[], void *p);
  57. int dotcpview (int argc, char *argv[], void *p);
  58. static int dotcpblimit (int argc, char *argv[], void *p);
  59. static int tcpblimit (int argc, char *argv[], void *p);
  60. static void rxtx_data_compute (struct tcb * tcb, int32 * sent, int32 * recvd);
  61. static int tstat (int flag);
  62. static int tstat2 (int flag);
  63.  
  64. #ifdef TCPACCESS
  65. struct rtaccess *TCPaccess = NULLACCESS;    /* access list */
  66. #endif
  67. extern int tcptimertype;
  68. extern long Tcp_maxwait;
  69. extern int Tcp_blimit;
  70.  
  71.  
  72. #ifdef CATALOG
  73. #include "catalog.h"
  74.  
  75. #define CAT tcpcmd_catalog
  76.  
  77. #define tracingstr    __STR(0)
  78. #define irttstr        __STR(1)
  79. #define irttdisp    __STR(2)
  80. #define mssstr        __STR(3)
  81. #define windowstr    __STR(4)
  82. #define syndatastr    __STR(5)
  83. #define retriesstr    __STR(6)
  84. #define maxwaitstr    __STR(7)
  85. #define backoffstr    __STR(8)
  86. #define cbheader    __STR(9)
  87. #define reassembly    __STR(10)
  88. #define reassstr    __STR(11)
  89. #define retrying    __STR(12)
  90. #define backoffval    __STR(13)
  91. #define timerstopped    __STR(14)
  92. #define timerrunning    __STR(15)
  93. #define timerexp    __STR(16)
  94. #define rttval        __STR(17)
  95. #define viewsyntax    __STR(18)
  96. #define viewhdr1    __STR(19)
  97. #define viewhdr2    __STR(20)
  98. #define timeris        __STR(21)
  99. #define timertypesyntax    __STR(22)
  100. #define accesshdr    __STR(23)
  101. #define accesssyntax    __STR(24)
  102. #define notfound    __STR(25)
  103.  
  104. #else /* CATALOG */
  105. static const char tracingstr[] = "TCP state tracing";
  106. static const char irttstr[] = "TCP default irtt";
  107. static const char irttdisp[] = "%s: srtt %lu mdev %lu\n";
  108. static const char mssstr[] = "TCP MSS";
  109. static const char windowstr[] = "TCP window";
  110. static const char syndatastr[] = "TCP syn+data piggybacking";
  111. static const char retriesstr[] = "max. retries";
  112. static const char maxwaitstr[] = "max. retry wait (ms)";
  113. static const char backoffstr[] = "backoff limit";
  114. static const char cbheader[] = "      Init seq    Unack     Next Resent CWind Thrsh  Wind  MSS Queue      Total\nSend:";
  115. static const char reassembly[] = "Reassembly queue:\n";
  116. static const char reassstr[] = "  seq x%lx %u bytes\n";
  117. static const char retrying[] = "Retrying ";
  118. static const char backoffval[] = "Backoff %u ";
  119. static const char timerstopped[] = "Timer stopped ";
  120. static const char timerrunning[] = "Timer running (%ld/%ld ms) ";
  121. static const char timerexp[] = "Timer expired ";
  122. static const char rttval[] = "SRTT %ld ms Mean dev %ld ms\n";
  123. static const char viewsyntax[] = "Use: tcp view <bytes|timers>\n";
  124. static const char viewhdr1[] = "                                                 Send    Send   Receive Receive\nRemote Socket:Port:Local Port/State    TCB      Bytes Retries     Bytes Retries\n";
  125. static const char viewhdr2[] = "Remote Socket:Port:Local Port/State    TCB   Boff State         Timer      SRTT\n";
  126. static const char timeris[] = "Tcp timer type is %s\n";
  127. static const char timertypesyntax[] = "use: tcp timertype [linear|exponential]\n";
  128. static const char accesshdr[] = "IP Address      Mask  Low Port High Port State\n";
  129. static const char accesssyntax[] = " Format: tcp access <permit|deny|delete> <dest addr>[/<bits>] [lowport [highport]]\n";
  130. static const char notfound[] = "Not found.\n";
  131.  
  132. #endif /* CATALOG */
  133.  
  134. static const char tstat2hdr[] =
  135. #if !defined(TNOS_68K) && !defined(UNIX)
  136. "&TCB Rcv-Q Snd-Q  Local socket           Remote socket          State\n";
  137. #else
  138. "&TCB     Rcv-Q Snd-Q  Local socket           Remote socket          State\n";
  139. #endif
  140.  
  141. static const char tstat2fmt[] =
  142. #if !defined(TNOS_68K) && !defined(UNIX)
  143. "%4.4x%6u%6u  ";
  144. #else
  145. "%-8.8lx%6u%6u  ";
  146. #endif
  147.  
  148. static const char str23[] = "%-23s";
  149. static const char tstatmib[] = "(%2u)%-20s%10lu";
  150. static const char str9lx[] = "%9lx";
  151. static const char str6u[] = "%6u";
  152. static const char spaces6[] = "      ";
  153. static const char spaces5[] = "     ";
  154. static const char linearstr[] = "linear";
  155. static const char exponentialstr[] = "exponential";
  156. static const char permitstr[] = "permit";
  157. static const char denystr[] = "deny";
  158. static const char allstr[] = "all";
  159. static const char deletestr[] = "delete";
  160. static const char viewretrystr[] = " Retry ";
  161. static const char viewtrystr[] = "  Try  ";
  162. static const char viewstopped[] = "      Stopped";
  163. static const char viewrun[] = " Run (";
  164. static const char view9999[] = ">9999/9999)s";
  165. static const char viewexp[] = "      Expired";
  166.  
  167.  
  168. /* TCP subcommand table */
  169. static struct cmds Tcpcmds[] =
  170. {
  171. #ifdef  TCPACCESS
  172.     { "access",        doaccess,    0, 0, NULLCHAR},
  173. #endif
  174.     { "blimit",        dotcpblimit,    0, 0, NULLCHAR},
  175.     { "connections",    dotcpconnect,    0, 0, NULLCHAR},
  176.     { "clean",        dotcpclean,    0, 0, NULLCHAR},
  177.     { "irtt",        dotcpirtt,    0, 0, NULLCHAR},
  178.     { "kick",        dotcpkick,    0, 2, "tcp kick <tcb>"},
  179.     { "maxwait",        dotcpmaxwait,    0, 0, NULLCHAR},
  180.     { "mss",        dotcpmss,    0, 0, NULLCHAR},
  181.     { "reset",        dotcpreset,    0, 2, "tcp reset <tcb>"},
  182.     { "retries",        dotcpretries,    0, 0, NULLCHAR},
  183.     { "rtt",        dortt,        0, 3, "tcp rtt <tcb> <val>"},
  184.     { "status",        dotcpstat,    0, 0, NULLCHAR},
  185.     { "syndata",        dotcpsyndata,    0, 0, NULLCHAR},
  186.     { "timertype",        dotcptimer,    0, 0, NULLCHAR},
  187.     { "trace",        dotcptr,    0, 0, NULLCHAR},
  188.     { "view",        dotcpview,    0, 0, NULLCHAR},
  189.     { "window",        dotcpwindow,    0, 0, NULLCHAR},
  190.     { NULLCHAR,        NULL,        0, 0, NULLCHAR}
  191. };
  192.  
  193.  
  194. int
  195. dotcp (argc, argv, p)
  196. int argc;
  197. char *argv[];
  198. void *p;
  199. {
  200.     return subcmd (Tcpcmds, argc, argv, p);
  201. }
  202.  
  203.  
  204. static int
  205. dotcptr (argc, argv, p)
  206. int argc;
  207. char *argv[];
  208. void *p OPTIONAL;
  209. {
  210.     return setbool (&Tcp_trace, tracingstr, argc, argv);
  211. }
  212.  
  213.  
  214. /* Reset lingering FIN Wait 2 state connections */
  215. static int
  216. dotcpclean (argc, argv, p)
  217. int argc OPTIONAL;
  218. char *argv[] OPTIONAL;
  219. void *p OPTIONAL;
  220. {
  221. struct tcb *tcb;
  222.  
  223.     for (tcb = Tcbs; tcb != NULLTCB; tcb = tcb->next) {
  224.         if (tcb->state == TCP_FINWAIT2) {
  225.             reset_tcp (tcb);
  226.             tcb = Tcbs;    /* start at the top again */
  227.         }
  228.     }
  229.     return 0;
  230. }
  231.  
  232.  
  233. /* Eliminate a TCP connection */
  234. static int
  235. dotcpreset (argc, argv, p)
  236. int argc OPTIONAL;
  237. char *argv[];
  238. void *p OPTIONAL;
  239. {
  240. register struct tcb *tcb;
  241.  
  242.     tcb = (struct tcb *) htoi (argv[1]);
  243.     if (!tcpval (tcb)) {
  244.         tputs (Notval);
  245.         return 1;
  246.     }
  247.     reset_tcp (tcb);
  248.     return 0;
  249. }
  250.  
  251.  
  252. /* Set initial round trip time for new connections */
  253. static int
  254. tcpirtt (argc, argv, p)
  255. int argc;
  256. char *argv[];
  257. void *p;
  258. {
  259.     return setlong ((long *) p, irttstr, argc, argv);
  260. }
  261.  
  262.  
  263. static int
  264. dotcpirtt (argc, argv, p)
  265. int argc;
  266. char *argv[];
  267. void *p OPTIONAL;
  268. {
  269. struct tcp_rtt *tp;
  270.  
  271.     (void) tcpirtt (argc, argv, (void *) &Tcp_irtt);
  272.     if (argc < 2) {
  273.         for (tp = &Tcp_rtt[0]; tp < &Tcp_rtt[RTTCACHE]; tp++) {
  274.             if (tp->addr != 0) {
  275.                 if (tprintf (irttdisp, inet_ntoa (tp->addr), tp->srtt, tp->mdev) == EOF)
  276.                     break;
  277.             }
  278.         }
  279.     }
  280.     return 0;
  281. }
  282.  
  283.  
  284. /* Set smoothed round trip time for specified TCB */
  285. static int
  286. dortt (argc, argv, p)
  287. int argc OPTIONAL;
  288. char *argv[];
  289. void *p OPTIONAL;
  290. {
  291. register struct tcb *tcb;
  292.  
  293.     tcb = (struct tcb *) htoi (argv[1]);
  294.     if (!tcpval (tcb)) {
  295.         tputs (Notval);
  296.         return 1;
  297.     }
  298.     tcb->srtt = atol (argv[2]);
  299.     return 0;
  300. }
  301.  
  302.  
  303. /* Force a retransmission */
  304. static int
  305. dotcpkick (argc, argv, p)
  306. int argc OPTIONAL;
  307. char *argv[];
  308. void *p OPTIONAL;
  309. {
  310. register struct tcb *tcb;
  311.  
  312.     tcb = (struct tcb *) htoi (argv[1]);
  313.     if (kick_tcp (tcb) == -1) {
  314.         tputs (Notval);
  315.         return 1;
  316.     }
  317.     return 0;
  318. }
  319.  
  320.  
  321. /* Set default maximum segment size */
  322. static int
  323. tcpmss (argc, argv, p)
  324. int argc;
  325. char *argv[];
  326. void *p;
  327. {
  328.     return setshort ((unsigned short *) p, mssstr, argc, argv);
  329. }
  330.  
  331.  
  332. static int
  333. dotcpmss (argc, argv, p)
  334. int argc;
  335. char *argv[];
  336. void *p OPTIONAL;
  337. {
  338.     return tcpmss (argc, argv, (void *) &Tcp_mss);
  339. }
  340.  
  341.  
  342. /* Set default window size */
  343. static int
  344. tcpwindow (argc, argv, p)
  345. int argc;
  346. char *argv[];
  347. void *p;
  348. {
  349.     return setshort ((unsigned short *) p, windowstr, argc, argv);
  350. }
  351.  
  352.  
  353. static int
  354. dotcpwindow (argc, argv, p)
  355. int argc;
  356. char *argv[];
  357. void *p OPTIONAL;
  358. {
  359.     return tcpwindow (argc, argv, (void *) &Tcp_window);
  360. }
  361.  
  362.  
  363. static int
  364. tcpsyndata (argc, argv, p)
  365. int argc;
  366. char *argv[];
  367. void *p;
  368. {
  369.     return setbool ((int *) p, syndatastr, argc, argv);
  370. }
  371.  
  372.  
  373. static int
  374. dotcpsyndata (argc, argv, p)
  375. int argc;
  376. char *argv[];
  377. void *p OPTIONAL;
  378. {
  379.     return tcpsyndata (argc, argv, (void *) &Tcp_syndata);
  380. }
  381.  
  382.  
  383. /* Set maximum number of backoffs before resetting the connection */
  384. static int
  385. tcpretries (argc, argv, p)
  386. int argc;
  387. char *argv[];
  388. void *p;
  389. {
  390.     return setint ((int *) p, retriesstr, argc, argv);
  391. }
  392.  
  393.  
  394. static int
  395. dotcpretries (argc, argv, p)
  396. int argc;
  397. char *argv[];
  398. void *p OPTIONAL;
  399. {
  400.     return tcpretries (argc, argv, (void *) &Tcp_retries);
  401. }
  402.  
  403.  
  404. /* Set maximum retry waittime in ms. */
  405. static int
  406. tcpmaxwait (argc, argv, p)
  407. int argc;
  408. char *argv[];
  409. void *p;
  410. {
  411.     return setlong ((long *) p, maxwaitstr, argc, argv);
  412. }
  413.  
  414.  
  415. static int
  416. dotcpmaxwait (argc, argv, p)
  417. int argc;
  418. char *argv[];
  419. void *p OPTIONAL;
  420. {
  421.     return tcpmaxwait (argc, argv, (void *) &Tcp_maxwait);
  422. }
  423.  
  424.  
  425. /* Set backoff limit on the connection; from N1BEE */
  426. static int
  427. tcpblimit (argc, argv, p)
  428. int argc;
  429. char *argv[];
  430. void *p;
  431. {
  432.     return setint ((int *) p, backoffstr, argc, argv);
  433. }
  434.  
  435.  
  436. static int
  437. dotcpblimit (argc, argv, p)
  438. int argc;
  439. char *argv[];
  440. void *p OPTIONAL;
  441. {
  442.     return tcpblimit (argc, argv, (void *) &Tcp_blimit);
  443. }
  444.  
  445.  
  446. /* Display status of TCBs */
  447. static int
  448. dotcpconnect (argc, argv, p)
  449. int argc;
  450. char *argv[];
  451. void *p OPTIONAL;
  452. {
  453. register struct tcb *tcb;
  454.  
  455.     if (argc < 2)
  456.         (void) tstat2 (0);
  457.     else {
  458.         if (toupper (argv[1][0]) == 'A')
  459.             (void) tstat (1);
  460.         else {
  461.             tcb = (struct tcb *) htoi (argv[1]);
  462.             if (!tcpval (tcb))
  463.                 tputs (Notval);
  464.             else
  465.                 st_tcp (tcb);
  466.         }
  467.     }
  468.     return 0;
  469. }
  470.  
  471.  
  472. /* Display status of TCBs with MIB info*/
  473. static int
  474. dotcpstat (argc, argv, p)
  475. int argc;
  476. char *argv[];
  477. void *p OPTIONAL;
  478. {
  479. register struct tcb *tcb;
  480.  
  481.     if (argc < 2)
  482.         (void) tstat (0);
  483.     else {
  484.         if (toupper (argv[1][0]) == 'A')
  485.             (void) tstat (1);
  486.         else {
  487.             tcb = (struct tcb *) htoi (argv[1]);
  488.             if (!tcpval (tcb))
  489.                 tputs (Notval);
  490.             else
  491.                 st_tcp (tcb);
  492.         }
  493.     }
  494.     return 0;
  495. }
  496.  
  497.  
  498. /* Dump TCP stats and summary of all TCBs
  499.  *     &TCB Rcv-Q Snd-Q  Local socket           Remote socket          State
  500.  *     1234     0     0  xxx.xxx.xxx.xxx:xxxxx  xxx.xxx.xxx.xxx:xxxxx  Established
  501.  * Dump display for TNOS_68K and UNIX
  502.  *     &TCB     Rcv-Q Snd-Q  Local socket           Remote socket          State
  503.  *     123456       0     0  xxx.xxx.xxx.xxx:xxxxx  xxx.xxx.xxx.xxx:xxxxx  Established
  504.  */
  505. static int
  506. tstat2 (int flag)
  507. {
  508. register struct tcb *tcb;
  509.  
  510.     tputs (tstat2hdr);
  511.     for (tcb = Tcbs; tcb != NULLTCB; tcb = tcb->next) {
  512.         if (tcb->state == TCP_LISTEN && !flag)
  513.             continue;
  514.         tprintf (tstat2fmt, tcb, tcb->rcvcnt, tcb->sndcnt);
  515.         tprintf (str23, pinet (&tcb->conn.local));
  516.         tprintf (str23, pinet (&tcb->conn.remote));
  517.         tprintf ("%-s", Tcpstates[(int) tcb->state]);
  518.         if (tcb->state == TCP_LISTEN && tcb->flags.clone)
  519.             tputs (" (S)");
  520.         if (tputc ('\n') == EOF)
  521.             return 0;
  522.     }
  523.     return 0;
  524. }
  525.  
  526.  
  527. static int
  528. tstat (int flag)
  529. {
  530. register int i;
  531. int j;
  532.  
  533.     for (j = i = 1; i <= NUMTCPMIB; i++) {
  534.         if (Tcp_mib[i].name == NULLCHAR)
  535.             continue;
  536.         tprintf (tstatmib, i, Tcp_mib[i].name,
  537.              Tcp_mib[i].value.integer);
  538.         if (j++ % 2)
  539.             tputs (spaces5);
  540.         else
  541.             tputc ('\n');
  542.     }
  543.     if ((j % 2) == 0)
  544.         tputc ('\n');
  545.  
  546.     return (tstat2 (flag));
  547. }
  548.  
  549.  
  550. /* Dump a TCP control block in detail */
  551. void
  552. st_tcp (tcb)
  553. struct tcb *tcb;
  554. {
  555. int32 sent, recvd;
  556.  
  557.     if (tcb == NULLTCB)
  558.         return;
  559.  
  560.     rxtx_data_compute (tcb, &sent, &recvd);
  561.  
  562.     tprintf ("Local: %s", pinet (&tcb->conn.local));
  563.     tprintf (" Remote: %s", pinet (&tcb->conn.remote));
  564.     tprintf (" State: %s\n", Tcpstates[(int) tcb->state]);
  565.     tputs (cbheader);
  566.     tprintf (str9lx, tcb->iss);
  567.     tprintf (str9lx, tcb->snd.una);
  568.     tprintf (str9lx, tcb->snd.nxt);
  569.     tprintf ("%7lu", tcb->resent);
  570.     tprintf (str6u, tcb->cwind);
  571.     tprintf (str6u, tcb->ssthresh);
  572.     tprintf (str6u, tcb->snd.wnd);
  573.     tprintf ("%5u", tcb->mss);
  574.     tprintf (str6u, tcb->sndcnt);
  575.     tprintf ("%11lu\n", sent);
  576.  
  577.     tputs ("Recv:");
  578.     tprintf (str9lx, tcb->irs);
  579.     tputs ("         ");
  580.     tprintf (str9lx, tcb->rcv.nxt);
  581.     tprintf ("%7lu", tcb->rerecv);
  582.     tputs (spaces6);
  583.     tputs (spaces6);
  584.     tprintf (str6u, tcb->rcv.wnd);
  585.     tputs (spaces5);
  586.     tprintf (str6u, tcb->rcvcnt);
  587.     tprintf ("%11lu\n", recvd);
  588.  
  589.     if (tcb->reseq != (struct reseq *) NULL) {
  590.         register struct reseq *rp;
  591.  
  592.         tputs (reassembly);
  593.         for (rp = tcb->reseq; rp != (struct reseq *) NULL; rp = rp->next) {
  594.             if (tprintf (reassstr, rp->seg.seq, rp->length) == EOF)
  595.                 return;
  596.         }
  597.     }
  598.     if (tcb->backoff > 0)
  599.         tprintf (backoffval, tcb->backoff);
  600.     if (tcb->flags.retran)
  601.         tputs (retrying);
  602.     switch (tcb->timer.state) {
  603.         case TIMER_STOP:
  604.             tputs (timerstopped);
  605.             break;
  606.         case TIMER_RUN:
  607.             tprintf (timerrunning,
  608.                  (long) read_timer (&tcb->timer),
  609.                  (long) dur_timer (&tcb->timer));
  610.             break;
  611.         case TIMER_EXPIRE:
  612.             tputs (timerexp);
  613.             break;
  614.         default:
  615.             break;
  616.     }
  617.     tprintf (rttval, tcb->srtt, tcb->mdev);
  618. }
  619.  
  620.  
  621. static void
  622. rxtx_data_compute (tcb, sent, recvd)
  623. struct tcb *tcb;
  624. int32 *sent;
  625. int32 *recvd;
  626. {
  627.  
  628.     /* Compute total data sent and received; take out SYN and FIN */
  629.     *sent = tcb->snd.una - tcb->iss;    /* Acknowledged data only */
  630.     *recvd = tcb->rcv.nxt - tcb->irs;
  631.     switch (tcb->state) {
  632.         case TCP_LISTEN:
  633.         case TCP_SYN_SENT:    /* Nothing received or acked yet */
  634.             *sent = *recvd = 0;
  635.             break;
  636.         case TCP_SYN_RECEIVED:
  637.             (*recvd)--;    /* Got SYN, no data acked yet */
  638.             *sent = 0;
  639.             break;
  640.         case TCP_ESTABLISHED:    /* Got and sent SYN */
  641.         case TCP_FINWAIT1:    /* FIN not acked yet */
  642.             (*sent)--;
  643.             (*recvd)--;
  644.             break;
  645.         case TCP_FINWAIT2:    /* Our SYN and FIN both acked */
  646.             *sent -= 2;
  647.             (*recvd)--;
  648.             break;
  649.         case TCP_CLOSE_WAIT:    /* Got SYN and FIN, our FIN not yet acked */
  650.         case TCP_CLOSING:
  651.         case TCP_LAST_ACK:
  652.             (*sent)--;
  653.             *recvd -= 2;
  654.             break;
  655.         case TCP_TIME_WAIT:    /* Sent and received SYN/FIN, all acked */
  656.             *sent -= 2;
  657.             *recvd -= 2;
  658.             break;
  659.         default:
  660.             break;
  661.     }
  662. }
  663.  
  664.  
  665. /* TCP View Command - D. Crompton 1/92 */
  666. /* Modified for sorted display and     */
  667. /* two views - tcp view b|t - 3/92     */
  668.  
  669. int
  670. dotcpview (argc, argv, p)
  671. int argc;
  672. char *argv[];
  673. void *p OPTIONAL;
  674. {
  675. register struct tcb *tcb;
  676. int32 sent, recvd;
  677. int i, j, k = 0, vtype;
  678. char temp[80];
  679. char *buf, *cp;
  680.  
  681.     if (argc == 1)
  682.         vtype = 1;
  683.     else {
  684.         switch (argv[1][0]) {
  685.             case 'b':
  686.                 vtype = 1;
  687.                 break;
  688.             case 't':
  689.                 vtype = 0;
  690.                 break;
  691.             default:
  692.                 tputs (viewsyntax);
  693.                 return 0;
  694.         }
  695.     }
  696.  
  697.     for (tcb = Tcbs, i = 0; tcb != NULLTCB; tcb = tcb->next) {
  698.         if (tcb->state == TCP_LISTEN)
  699.             continue;
  700.         i++;
  701.     }
  702.  
  703.     if (i) {
  704.         buf = mallocw ((unsigned) (i * 80));
  705.  
  706.         if (vtype)
  707.             tputs (viewhdr1);
  708.         else
  709.             tputs (viewhdr2);
  710.  
  711.         for (tcb = Tcbs, j = 0; tcb != NULLTCB; tcb = tcb->next) {
  712.             if (tcb->state == TCP_LISTEN)
  713.                 continue;
  714.  
  715.             strncpy (temp, pinet (&tcb->conn.remote), 80);
  716.             cp = strstr (pinet (&tcb->conn.local), ":");
  717.             if (cp)
  718.                 strcat (temp, cp);
  719.             strcat (temp, "/");
  720.             strcat (temp, Tcpstates[(int) tcb->state]);
  721.             temp[37] = 0;
  722.             k = SPRINTF ((&buf[j], "%-35.35s", temp));
  723.             sprintf (temp, "%8lx", ptol (tcb));
  724. #if 0
  725.             temp[4] = 0;
  726.             k += SPRINTF ((&buf[j + k], " %4s", temp));
  727. #else
  728.             k += SPRINTF ((&buf[j + k], " %8s", temp));
  729. #endif
  730.             if (vtype) {
  731.                 rxtx_data_compute (tcb, &sent, &recvd);
  732.                 k += SPRINTF ((&buf[j + k], "%9lu ", sent));
  733.                 k += SPRINTF ((&buf[j + k], "%7lu ", tcb->resent));
  734.                 k += SPRINTF ((&buf[j + k], "%9lu ", recvd));
  735.                 sprintf (&buf[j + k], "%7lu", tcb->rerecv);
  736.             } else {
  737.                 k += SPRINTF ((&buf[j + k], " %4u", tcb->backoff));
  738.                 if (tcb->flags.retran)
  739.                     k += SPRINTF ((&buf[j + k], viewretrystr));
  740.                 else
  741.                     k += SPRINTF ((&buf[j + k], viewtrystr));
  742.                 switch (tcb->timer.state) {
  743.                     case TIMER_STOP:
  744.                         k += SPRINTF ((&buf[j + k], viewstopped));
  745.                         break;
  746.                     case TIMER_RUN:
  747.                         k += SPRINTF ((&buf[j + k], viewrun));
  748.                         if ((long) dur_timer (&tcb->timer) < 10000) {
  749.                             k += SPRINTF ((&buf[j + k], "%ld/%ld)ms",
  750.                                        (long) read_timer (&tcb->timer),
  751.                                        (long) dur_timer (&tcb->timer)));
  752.                         } else {
  753.                             if (((long) read_timer (&tcb->timer) / 1000) > 9999) {
  754.                                 k += SPRINTF ((&buf[j + k], view9999));
  755.                             } else {
  756.                                 k += SPRINTF ((&buf[j + k], "%ld/%ld)s",
  757.                                            (long) read_timer (&tcb->timer) / 1000,
  758.                                            (long) dur_timer (&tcb->timer) / 1000));
  759.                             }
  760.                         }
  761.                         break;
  762.                     case TIMER_EXPIRE:
  763.                         k += SPRINTF ((&buf[j + k], viewexp));
  764.                         break;
  765.                     default:
  766.                         break;
  767.                 }
  768.                 for (; k < 73; k++)
  769.                     buf[j + k] = ' ';
  770.                 if ((tcb->srtt) < 10000)
  771.                     sprintf (&buf[j + 73], "%4ldms", tcb->srtt);
  772.                 else {
  773.                     if ((tcb->srtt / 1000) > 9999) {
  774.                         sprintf (&buf[j + 73], ">9999s");
  775.                     } else {
  776.                         sprintf (&buf[j + 73], "%4lds", tcb->srtt / 1000);
  777.                     }
  778.                 }
  779.             }
  780.             j += 80;
  781.         }
  782.  
  783.         qsort (buf, (size_t) i, 80, (int (*)(const void *, const void *)) strcmp);
  784.         for (j = 0, k = 0; j < i; j++, k += 80) {
  785.             tputs (&buf[k]);
  786.             if (tputc ('\n') == EOF)
  787.                 return 0;
  788.         }
  789.         free (buf);
  790.     }
  791.     return 0;
  792. }
  793.  
  794.  
  795. /* tcp timers type - linear v exponential */
  796. static int
  797. tcptimer (argc, argv, p)
  798. int argc;
  799. char *argv[];
  800. void *p;
  801. {
  802.     if (argc < 2) {
  803.         tprintf (timeris, *(int *) p ? linearstr : exponentialstr);
  804.         return 0;
  805.     }
  806.     switch (argv[1][0]) {
  807.         case 'l':
  808.         case 'L':
  809.             *(int *) p = 1;
  810.             break;
  811.         case 'e':
  812.         case 'E':
  813.             *(int *) p = 0;
  814.             break;
  815.         default:
  816.             tputs (timertypesyntax);
  817.             return -1;
  818.     }
  819.  
  820.     return 0;
  821. }
  822.  
  823.  
  824. static int
  825. dotcptimer (argc, argv, p)
  826. int argc;
  827. char *argv[];
  828. void *p OPTIONAL;
  829. {
  830.  
  831.     return tcptimer (argc, argv, (void *) &tcptimertype);
  832. }
  833.  
  834.  
  835. #if defined(TCPACCESS) || defined(UDPACCESS)
  836.  
  837. int
  838. do_tcpudp_access (argc, argv, p)
  839. int argc;
  840. char *argv[];
  841. void *p;
  842. {
  843. uint32 target;
  844. unsigned bits;
  845. char *bitp;
  846. int16 lport, hport, state;
  847. char const *cp;        /* for printing the table */
  848. struct rtaccess *tpacc;
  849. struct rtaccess **headptr = (struct rtaccess **)p;
  850. struct rtaccess *head;
  851. struct rtaccess *prev;
  852.  
  853.     if (argc == 1) {    /* print out the table */
  854.         tputs (accesshdr);
  855.         for (tpacc = *headptr; tpacc != NULLACCESS; tpacc = tpacc->nxtbits) {
  856.             if (tpacc->target != 0)
  857.                 cp = inet_ntoa (tpacc->target);
  858.             else
  859.                 cp = allstr;
  860.             tprintf ("%-16s", cp);
  861.             tprintf ("%4u ", tpacc->bits);
  862.             tprintf ("%9u", tpacc->lowport);
  863.             tprintf ("%10u ", tpacc->highport);
  864.             if (tpacc->status)
  865.                 cp = denystr;
  866.             else
  867.                 cp = permitstr;
  868.             tprintf ("%-6s\n", cp);
  869.         }
  870.         return 0;
  871.     }
  872.     if (strcmp (argv[1], permitstr) == 0)
  873.         state = 0;
  874.     else {
  875.         if ((strcmp (argv[1], "deny") == 0) || (strcmp (argv[1], "delete") == 0))
  876.             state = (int16) - 1;
  877.         else {
  878.             tputs (accesssyntax);
  879.             return 1;
  880.         }
  881.     }
  882.     if (strcmp (argv[2], allstr) == 0) {
  883.         target = 0;
  884.         bits = 0;
  885.     } else {
  886.         /* If IP address is followed by an optional slash and
  887.          * a length field, (e.g., 128.96/16) get it;
  888.          * otherwise assume a full 32-bit address
  889.          */
  890.         if ((bitp = strchr (argv[2], '/')) != NULLCHAR) {
  891.             /* Terminate address token for resolve() call */
  892.             *bitp++ = '\0';
  893.             bits = (unsigned) atoi (bitp);
  894.         } else
  895.             bits = 32;
  896.  
  897.         if ((target = resolve (argv[2])) == 0) {
  898.             tprintf (Badhost, argv[2]);
  899.             return 1;
  900.         }
  901.     }
  902.  
  903.     if (argc > 3) {
  904.         if (strcmp (argv[3], allstr) == 0) {
  905.             lport = 1;
  906.             hport = 65534L;
  907.         } else {
  908.             lport = (int16) atoi (argv[3]);
  909.             hport = lport;
  910.         }
  911.     } else {
  912.         lport = 0;
  913.         hport = 0;
  914.     }
  915.     if (argc > 4)
  916.         hport = (int16) atoi (argv[4]);
  917.  
  918.     if (strcmp (argv[1], deletestr) == 0) {
  919.         prev = NULLACCESS;
  920.         head = tpacc = *headptr;
  921.         while (tpacc != NULLACCESS) {
  922.             head = tpacc;
  923.             tpacc = tpacc->nxtbits;
  924.             if ((head->target == target) && (head->bits == bits) &&
  925.                 (head->lowport == lport) && (head->highport == hport)) {    /*match*/
  926.                 /*now delete. watch for special cases*/
  927.                 if (head == *headptr)    /* first in chain */
  928.                     *headptr = head->nxtbits;
  929.                 else    {
  930.                     /* sanity check: we cant get here with prev == NULLACCESS !! */
  931.                     if (prev)
  932.                         prev->nxtbits = tpacc;
  933.                 }
  934.                 free (head);
  935.                 return 0;
  936.             }
  937.             prev = head;
  938.         }
  939.         tputs (notfound);
  940.         return 1;
  941.     }
  942.     /* add the access */
  943.     addtaccess (headptr, target, bits, lport, hport, state);
  944.     return 0;
  945. }
  946.  
  947.  
  948.  
  949. static int
  950. doaccess (argc, argv, p)
  951. int argc;
  952. char *argv[];
  953. void *p OPTIONAL;
  954. {
  955.     return (do_tcpudp_access (argc, argv, &TCPaccess));
  956. }
  957.  
  958.  
  959.  
  960. /*lint -esym(18,addtaccess) */
  961. /* add an entry to the access control list */
  962. /* not a lot of error checking 8-) */
  963. static void
  964. addtaccess (headacc, target, bits, low, high, permit)
  965. struct rtaccess **headacc;
  966. uint32 target;            /* Target IP address prefix */
  967. unsigned int bits;        /* Size of target address prefix in bits (0-32) */
  968. int16 low;
  969. int16 high;
  970. int16 permit;
  971. {
  972. struct rtaccess *tpacc;        /*temporary*/
  973. struct rtaccess *holder;    /*for the new record*/
  974.  
  975.     holder = (struct rtaccess *) callocw (1, sizeof (struct rtaccess));
  976.  
  977.     holder->nxtiface = NULLACCESS;
  978.     holder->nxtbits = NULLACCESS;
  979.     holder->target = target;
  980.     holder->bits = bits;
  981.     holder->lowport = low;
  982.     holder->highport = high;
  983.     holder->status = permit;
  984.  
  985.     if ((low || high) && (*headacc == NULLACCESS || tcp_check (*headacc, target, low) == -1))
  986.         addtaccess (headacc, target, bits, 0, 0, ~permit);
  987.  
  988.     if ((tpacc = *headacc) == NULLACCESS)
  989.         *headacc = holder;
  990.     else {
  991.         while (tpacc->nxtbits != NULLACCESS)
  992.             tpacc = tpacc->nxtbits;
  993.         tpacc->nxtbits = holder;
  994.     }
  995. }
  996.  
  997.  
  998.  
  999. /*lint -esym(18,tcp_check) */
  1000. /* check to see if port is "authorized".  Returns 0 if matching permit record
  1001.    is found or no access records exists, -1 if not found or deny record found */
  1002. int
  1003. tcp_check (accptr, src, port)
  1004. struct rtaccess *accptr;
  1005. uint32 src;
  1006. int16 port;
  1007. {
  1008. unsigned long mask;
  1009. unsigned short tmp;
  1010. int retval = -1;
  1011.  
  1012.     if (accptr == NULLACCESS)
  1013.         return 0;    /* no access control */
  1014.     for (; accptr != NULLACCESS; accptr = accptr->nxtbits) {
  1015.         tmp = (int16) (32 - accptr->bits);
  1016.         if (tmp == 32)    /* accptr == 0 !! */
  1017.             mask = 0;        /* GCC bug?? */
  1018.         else
  1019.             mask = ~0L << tmp;    /*lint !e703 */
  1020.         if ((accptr->target == (uint32) (mask & src)) &&
  1021.           (((port >= accptr->lowport) && (port <= accptr->highport))
  1022.            || (!accptr->lowport))) {
  1023.                /* if this is a default entry, save the status,
  1024.                   but look in case there is a more specific entry
  1025.                   later in the list. If not, upon exit, we will
  1026.                   return the proper status
  1027.                 */
  1028.                if (!accptr->lowport && !accptr->highport)
  1029.                    retval = accptr->status;
  1030.                else
  1031.                 return (accptr->status);
  1032.         }
  1033.     }
  1034.     return retval;        /* fall through to here if specific entry not found */
  1035. }
  1036.  
  1037. #endif
  1038.  
  1039.  
  1040. /* These are the interface dependent tcp parameters */
  1041. static int doiftcpblimit (int argc, char *argv[], void *p);
  1042. static int doiftcpirtt (int argc, char *argv[], void *p);
  1043. static int doiftcpmaxwait (int argc, char *argv[], void *p);
  1044. static int doiftcpretries (int argc, char *argv[], void *p);
  1045. static int doiftcptimertype (int argc, char *argv[], void *p);
  1046. static int doiftcpwindow (int argc, char *argv[], void *p);
  1047. static int doiftcpsyndata (int argc, char *argv[], void *p);
  1048. static int doiftcpmss (int argc, char *argv[], void *p);
  1049.  
  1050.  
  1051. static struct cmds Iftcpcmds[] =
  1052. {
  1053.     { "blimit",    doiftcpblimit,        0, 0, NULLCHAR},
  1054.     { "irtt",    doiftcpirtt,        0, 0, NULLCHAR},
  1055.     { "maxwait",    doiftcpmaxwait,        0, 0, NULLCHAR},
  1056.     { "mss",    doiftcpmss,        0, 0, NULLCHAR},
  1057.     { "retries",    doiftcpretries,        0, 0, NULLCHAR},
  1058.     { "syndata",    doiftcpsyndata,        0, 0, NULLCHAR},
  1059.     { "timertype",    doiftcptimertype,    0, 0, NULLCHAR},
  1060.     { "window",    doiftcpwindow,        0, 0, NULLCHAR},
  1061.     { NULLCHAR,    NULL,            0, 0, NULLCHAR}
  1062. };
  1063.  
  1064.  
  1065. int 
  1066. doiftcp (int argc, char *argv[], void *p)
  1067. {
  1068.     if (!p)
  1069.         return 0;
  1070.     return subcmd (Iftcpcmds, argc, argv, p);
  1071. }
  1072.  
  1073.  
  1074. int 
  1075. doiftcpblimit (int argc, char *argv[], void *p)
  1076. {
  1077. struct iface *ifp = p;
  1078.  
  1079.     return tcpblimit (argc, argv, (void *) &ifp->tcp->blimit);
  1080. }
  1081.  
  1082.  
  1083. int 
  1084. doiftcpirtt (int argc, char *argv[], void *p)
  1085. {
  1086. struct iface *ifp = p;
  1087.  
  1088.     return tcpirtt (argc, argv, (void *) &ifp->tcp->irtt);
  1089. }
  1090.  
  1091.  
  1092. int 
  1093. doiftcpmaxwait (int argc, char *argv[], void *p)
  1094. {
  1095. struct iface *ifp = p;
  1096.  
  1097.     return tcpmaxwait (argc, argv, (void *) &ifp->tcp->maxwait);
  1098. }
  1099.  
  1100.  
  1101. int 
  1102. doiftcpmss (int argc, char *argv[], void *p)
  1103. {
  1104. struct iface *ifp = p;
  1105.  
  1106.     return tcpmss (argc, argv, (void *) &ifp->tcp->mss);
  1107. }
  1108.  
  1109.  
  1110. int 
  1111. doiftcpretries (int argc, char *argv[], void *p)
  1112. {
  1113. struct iface *ifp = p;
  1114.  
  1115.     return tcpretries (argc, argv, (void *) &ifp->tcp->retries);
  1116. }
  1117.  
  1118.  
  1119. int 
  1120. doiftcptimertype (int argc, char *argv[], void *p)
  1121. {
  1122. struct iface *ifp = p;
  1123.  
  1124.     return tcptimer (argc, argv, (void *) &ifp->tcp->timertype);
  1125. }
  1126.  
  1127.  
  1128. int 
  1129. doiftcpwindow (int argc, char *argv[], void *p)
  1130. {
  1131. struct iface *ifp = p;
  1132.  
  1133.     return tcpwindow (argc, argv, (void *) &ifp->tcp->window);
  1134. }
  1135.  
  1136.  
  1137. int 
  1138. doiftcpsyndata (int argc, char *argv[], void *p)
  1139. {
  1140. struct iface *ifp = p;
  1141.  
  1142.     return tcpsyndata (argc, argv, (void *) &ifp->tcp->syndata);
  1143. }
  1144.  
  1145.  
  1146. void 
  1147. init_iftcp (struct iftcp *tcp)
  1148. {
  1149.     tcp->blimit = Tcp_blimit;
  1150.     tcp->maxwait = Tcp_maxwait;
  1151.     tcp->window = Tcp_window;
  1152.     tcp->mss = Tcp_mss;
  1153.     tcp->irtt = Tcp_irtt;
  1154.     tcp->retries = Tcp_retries;
  1155.     tcp->timertype = tcptimertype;
  1156.     tcp->syndata = Tcp_syndata;
  1157. }
  1158.